﻿/* 
 *  <copyright file="WorldMapUser.cs" company="Wesley Jowitt">
 *  
 *  SobrietyEngine: Copyright (c) 2011 Wesley Jowitt
 *  
 *  This software is distributed under a software license.
 *   * As of the creation time of this file, the license in use is the Microsoft Permissive License (Ms-PL) 
 *    * The license can be viewed at:
 *     * License.Txt in the root folder of this project
 *      * http://sobrietyengine.codeplex.com/license
 *       * http://www.microsoft.com/opensource/licenses.mspx
 *       
 *  </copyright>
 *   */

using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using SobrietyEngine.Actor;
using SobrietyEngine.Components;
using SobrietyEngine.Components.Controller;
using SobrietyEngine.Components.Paths;
using SobrietyEngine.Events;
using SobrietyEngine.Events.UserActions;
using SobrietyEngine.Guids;
using SobrietyEngine.Logging;

namespace SEGameExample.Components.Controllers
{
    public class WorldMapUser: ControllerCmp, IComponent, IEventListener
    {      
        IPosition PositionComp = null;
        Vector3 Move = Vector3.Zero;

        IMovement movementComp;

        //PathFollowerCmp pathCmp;
        PathNodeCmp currentPathNode;
        CGuid startingPathNode;
        
        float useRange = 0.05f;

        CGuid OwningUser { get; set; }

        public WorldMapUser(CGuid userGuid, CGuid _startingPathNode)
            : base()
        {
            OwningUser = userGuid;
            startingPathNode = _startingPathNode;
        }

        override public Type[] SupportedInterfaces()
        {
            return new Type[] { typeof(IController) };
        }

        override public Boolean InitComponent()
        {
            //get our components
            PositionComp = Actor.Get<IPosition>();
            currentPathNode = startingPathNode.Resolve<IActor>().Get<PathNodeCmp>();
            movementComp = Actor.Get<IMovement>();

            //check our components, make sure they are what we expect
            if (PositionComp == null || currentPathNode == null || movementComp == null)               
            {
                Logger.Debug(this, "Missing components: delaying init");
                return false;
            }

            //set our first path node target
            movementComp.SetTarget(currentPathNode.PositionV2);

            //add controller listener events
            RegisterEventListeners();

            return true;
        }

        public virtual void RegisterEventListeners()
        {
            Actor.EventRouter.AddEventListener(typeof(Move), this);
            Actor.EventRouter.AddEventListener(typeof(Use), this);
        }

        public new void Remove()
        {
            //remove controller listener events
            UnregisterEventListeners();
        }

        public virtual void UnregisterEventListeners()
        {
            Actor.EventRouter.RemoveEventListener(this);
        }

        public void HandleEvent(Event e)
        {
            //not enabled, exit out
            if (!Enabled)
                return;

            //if this event is not from the owning player
            if(OwningUser != e.From)
                return;

            //handle our move event
            if (e.Type == typeof(Move))
            {
                Move m = (Move)e.Data;
                Move = m.MoveBy;
            }

            //handle use - need to convert to a Scene based 'actor action' 
            else if (e.Type == typeof(SobrietyEngine.Events.UserActions.Use))
            {
                SobrietyEngine.Events.ActorActions.Use use =
                    new SobrietyEngine.Events.ActorActions.Use(Actor, PositionComp.PositionV3, useRange);
                Actor.EventRouter.RaiseEvent(this, use);
            }
        }

        public new void Update(GameTime ElapsedTime)
        {
            if (movementComp.HasTarget == false && Move != Vector3.Zero)
            {
                
                //we are at our target, select the next taget mode and get to moving
                List<IActor> nextNodes = currentPathNode.GetNextPathNodeActors();
                if (nextNodes.Count == 0)
                    Logger.Error(this, "next path node not found@!");

                //move towards the one tha we have pressed towards with joystick
                foreach (IActor nodeActor in nextNodes)
                {
                    IPosition nodePos = nodeActor.Get<IPosition>();
                    Vector3 dir = nodePos.PositionV3 - PositionComp.PositionV3;
                    float dotNext = Vector3.Dot(Move, dir);
                    if (dotNext > 0)
                    {
                        currentPathNode = nodeActor.Get<PathNodeCmp>();
                        //and set our mover to startheading towards the target, if we have a mover
                        if (movementComp != null)
                            movementComp.SetTarget(currentPathNode.PositionV2);
                        break;
                    }
                    
                }                
            }
        }
    }
}